/**
 * @Author: weipc 755197142@qq.com
 * @Date: 2024-12-03 15:33:16
 * @LastEditors: weipc 755197142@qq.com
 * @LastEditTime: 2025-02-11 10:34:32
 * @FilePath: src/core/fetch/index.ts
 * @Description: 配置 alova.js 实例
 */

import { createAlova } from "alova";
import adapterFetch from "alova/fetch";
import VueHook from "alova/vue";
import { ResultEnum } from "@/enums/httpEnum";
import { createClientTokenAuthentication } from "alova/client";
import { handleServiceResult } from "@/core/fetch/handle";
import { useUserStore } from "@/stores/modules/user";
import router from "@/routers";
import { LOGIN_URL } from "@/config";
import { ElMessage } from "element-plus";

// 基础 alova 配置

const alovaOptions = {
  baseURL: import.meta.env.VITE_API_URL as string, // API 基础 URL
  timeout: ResultEnum.TIMEOUT as number, // 超时时间
  requestAdapter: adapterFetch(), // 请求适配器
  statesHook: VueHook, // 状态管理钩子
  cacheFor: null
};

// 绑定 token 认证拦截器
const { onAuthRequired, onResponseRefreshToken } = createClientTokenAuthentication({
  async login(response) {
    try {
      const responseData = await response.clone().json();
      if (responseData.code === 0) {
        useUserStore().setToken(responseData.data.accessToken);
      }
    } catch (e) {
      ElMessage.error((e as any).message);
      throw e;
    }
  },
  assignToken: method => {
    const userStore = useUserStore();
    method.config.headers["Authorization"] = `Bearer ${userStore.token}`;
  }
});

// alova 实例
const alovaInstance = createAlova({
  ...alovaOptions,
  beforeRequest: onAuthRequired(method => {
    method.config.cacheFor = 0;
  }),
  responded: onResponseRefreshToken({
    async onSuccess(response, method) {
      const responseClone = response.clone();
      try {
        const responseData = await (method.meta?.isBlob ? responseClone.blob() : responseClone.json());

        // 成功处理
        if (responseClone.status === ResultEnum.SUCCESS && responseData.code === 0) {
          return handleServiceResult(responseData);
        }

        // 处理非成功状态
        const message = responseData.message || response.statusText;

        // token 过期处理
        if (responseClone.status === ResultEnum.OVERDUE) {
          console.warn("Token expired, redirecting to login...");
          useUserStore().setToken("");
          await router.replace(LOGIN_URL);
        }

        await Promise.reject(message);
        return handleServiceResult(responseData, false);
      } catch (err: any) {
        ElMessage.error(err.message ? err.message : JSON.stringify(err));
        throw err;
      }
    },
    onError(error) {
      ElMessage.error(`Request failed: ${error.message}`);
    }
  })
});

export { alovaInstance };
